﻿using MiniFox;
using MiniFox.Components;
using MiniFox.Data.EntityFramework;
using MiniFox.Infrastructure;
using MiniFox.Platform;
using MiniFox.Platform.Applications.Models;
using MiniFox.Utility;
using Repository.Core;
using Repository.Core.Models.Queries;
using Repository.Core.Models.VO;
using Repository.Core.Providers;
using Repository.Data.Entities.MySql;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Repository.Data
{
    [AutoResolve]
    public class PublishProvider : EntityDataProvider<RepositoryContext>, IPublishProvider
    {
        public string GetItemContent(string repoName, string versionSetName)
        {
            var versionSet = this.CurrentDbContext.VersionSet.SingleOrDefault(vs => vs.RepoName == repoName && vs.Name == versionSetName);
            if (versionSet == null || versionSet.PubId == null || versionSet.PubId == string.Empty) return null;

            var pub = this.CurrentDbContext.PublishLog.SingleOrDefault(p => p.Id == versionSet.PubId);
            if (pub == null) return null;

            var item = this.CurrentDbContext.VersionItem.SingleOrDefault(v => v.Id == pub.VersionId);
            if (item == null) return null;

            return item.Content;
        }

        public bool Publish(string repoName, SystemIdentity identity, string versionSetName, long? versionId)
        {
            var versionItems = from v in this.CurrentDbContext.VersionItem
                               where v.RepoName == repoName && v.VersionSetName == versionSetName
                               orderby v.VersionTime descending
                               select v;

            VersionItem version;
            if (versionId == null)
            {
                version = versionItems.FirstOrDefault();
            }
            else
            {
                version = versionItems.SingleOrDefault(v => v.Id == versionId);
            }
            if (version == null)
                return false;
            var versionSet = this.CurrentDbContext.VersionSet.SingleOrDefault(v => v.RepoName == repoName && v.Name == versionSetName);
            if (versionSet == null) 
                return false;

            var logId = new Sequence(new SequenceSetting(string.Empty, string.Empty, "yyyyMMddHHmmss", 4, false, MiniFox.Utility.CodeType.Number));
            versionSet.PubId = logId;
            List <BatchOperationItem> list =
            [
                new BatchOperationItem
                {
                    Entity = new PublishLog
                    {
                        Id = logId,
                        PublisherId = identity.GlobalID,
                        PublisherName = identity.CombineUserName(),
                        PublishTime = DateTime.Now,
                        VersionId = version.Id
                    },
                    State = Microsoft.EntityFrameworkCore.EntityState.Added
                },
                new BatchOperationItem
                {
                    Entity = versionSet,
                    State = Microsoft.EntityFrameworkCore.EntityState.Modified
                },
            ];

            return this.CommitBatch(list) > 0;
        }

        public ResultObject<IEnumerable<PublishVo>> Query(string repoName, PagedQueryObject<CommonQuery> request)
        {
            var query = from v in this.CurrentDbContext.VersionSet
                        join p in this.CurrentDbContext.PublishLog on v.PubId equals p.Id
                        join i in this.CurrentDbContext.VersionItem on p.VersionId equals i.Id
                        where v.RepoName == repoName && v.PubId != null
                        select new
                        {
                            VersionSetName = v.Name,
                            v.RepoName,
                            v.PubId,
                            v.Description,
                            v.UpdateTime,
                            p.PublisherId,
                            p.PublisherName,
                            p.PublishTime,
                            VersionId = i.Id,
                            i.AuthorId,
                            i.AuthorName,
                            i.Comment
                        };
            var result = this.PagedQueryExecute(query, request);
            return result.GetResultObject(r => new PublishVo
            {
                Name = r.VersionSetName,
                VersionId = r.VersionId,
                PublisherId = r.PublisherId,
                PublisherName = r.PublisherName,
                PublishTime = r.PublishTime,
                AuthorId = r.AuthorId,
                AuthorName = r.AuthorName,
                Comment = r.Comment
            });
        }
    }
}
